Questions
13 of 13
1Why does Qdrant recommend disabling indexing (or raising the indexing threshold) during a large bulk import, then re-enabling it afterward?
2What is the purpose of the indexing_threshold setting, and how does it affect small versus large collections differently?
3How does GPU-accelerated indexing change the economics of re-indexing a large, frequently-updated collection?
4What is incremental HNSW indexing, and why does it matter for upsert-heavy workloads?
5Your Qdrant search endpoint's p50 latency looks fine, but p99 latency is very high. What are the most likely causes to investigate first?
6How would you reduce query latency for a collection that must remain on-disk due to its size, without moving the whole collection into RAM?
7What is the effect of increasing the number of search threads/parallelism on a single node with limited CPU cores?
8How would you benchmark whether a proposed quantization configuration is worth the accuracy trade-off for your workload?
9What's the difference between scaling Qdrant vertically (bigger node) and horizontally (more shards/nodes), and when does horizontal scaling stop paying off?
10Two teams store the same 50-million-vector collection - one keeps it fully in memory, one on disk with quantization. What operational differences should each expect?
11Why can moving the payload storage engine on-disk versus in-memory have a bigger impact on filtered-search latency than the vector storage location?
12How would you decide, for a specific collection, whether to enable quantization with rescoring versus simply moving vectors on-disk without quantization?
13What memory overhead does the HNSW graph itself add on top of the raw vector data, and why does that matter when planning RAM for an in-memory collection?
13 / 13

What memory overhead does the HNSW graph itself add on top of the raw vector data, and why does that matter when planning RAM for an in-memory collection?

The graph adds roughly 2*m edges per point on layer 0, plus upper layers

The HNSW graph is not free. On layer 0, each point stores up to 2*m neighbor links because edges are bidirectional, so a point with m=16 has up to 32 links. Each link is an integer point ID, typically 4 or 8 bytes depending on the ID type and the internal representation. That is roughly 128 to 256 bytes per point on layer 0 alone, before you count the upper layers. The upper layers add a fraction on top - each point has a probability of appearing in each higher layer, and the expected total number of links across all layers is layer_0_links times a factor that depends on m, roughly 1.1 to 1.3 for typical m. So for a collection of 100 million points with m=16 and 4-byte IDs, the graph alone is on the order of 13 to 17 GB. That is on top of the raw vectors (100M * 768 * 4 bytes = ~307 GB for float32) and on top of the payload indexes and point metadata.

The reason this matters for in-memory capacity planning is that teams routinely size RAM by counting vector bytes and then are surprised when the node runs out of memory. The graph is not a small overhead - for typical m values it is a meaningful fraction of the total, and it grows linearly with point count. It also grows with m, so raising m to improve recall has a direct memory cost that is easy to underestimate. Payload indexes are a third component that is easy to forget: keyword indexes, range indexes, and full-text indexes all consume memory, and their size depends on the cardinality and the number of indexed fields. Point metadata - the IDs, the version numbers, the tombstones - also adds a per-point overhead. When you are planning a node's RAM, the correct estimate is the sum of all of these, not just the vectors. A useful rule of thumb for an in-memory collection is to add 30 to 60 percent to the raw vector bytes to account for the graph, payload indexes, and metadata, with the exact figure depending on m and on the number of indexed fields.

  1. 1

    Layer 0: up to 2*m links per point, each link an integer ID (4 or 8 bytes).

  2. 2

    Upper layers: add roughly 10-30 percent on top of layer 0 for typical m values.

  3. 3

    Graph memory scales linearly with point count and with m, so raising m for recall costs memory directly.

  4. 4

    Payload indexes: separate structures whose size depends on field cardinality and count.

  5. 5

    Point metadata: IDs, versions, and tombstones add a per-point overhead.

  6. 6

    Planning rule: for in-memory collections, add 30-60 percent to the raw vector bytes to account for graph, indexes, and metadata.

The trade-off is that the graph overhead is the price of sub-linear search. Without the graph, every query would be a linear scan, which is unacceptable at scale. With the graph, you pay memory proportional to m and to point count, in exchange for logarithmic search. The common mistake is sizing RAM by the vector data alone and then discovering that a 100M-point collection needs substantially more than the vector bytes suggest. The second mistake is raising m to fix recall without accounting for the memory increase, especially on a node that is already close to capacity. The third mistake is forgetting the payload indexes, which on collections with many indexed fields can be a significant fraction of the total. The alternative to carrying the graph in RAM is to put it on disk, either entirely or with the quantized vectors inline; that trades the memory cost for I/O, which may be acceptable depending on the latency SLO. Version note: the exact graph memory overhead depends on the ID representation and on the internal storage layout, both of which have changed across Qdrant releases. The upper-layer multiplier and the way links are stored may differ, so a plan that was accurate on one version may be off on another. Measure the actual memory usage on your version rather than relying on a fixed multiplier.

javascript

Version-dependent: the internal representation of graph links and point IDs has changed across Qdrant releases, as has the upper-layer structure. The memory overhead per point is therefore not a fixed constant across versions. If you are planning a large in-memory deployment, measure the actual RSS of a representative collection on your version rather than extrapolating from a formula, and re-measure after upgrades that touch the storage engine.

Difficulty: 7/10
Topics: HNSW, Memory Optimization, Capacity Planning

Scenario Questions

0-2 years experience
  1. 1

    You size a node for 50M vectors and it runs out of RAM. Explain what components you probably forgot and how you would redo the estimate.

  2. 2

    A teammate raises m from 16 to 48 to improve recall. Explain the memory impact and whether it is worth it.

2-5 years experience
  1. 1

    You need to fit a 30M-vector collection on a node with 128 GB of RAM. Walk through the full memory estimate, including vectors, graph, and payload indexes, and decide whether it fits.

  2. 2

    Your collection uses 20 percent more RAM than your estimate predicted. List the likely sources of the discrepancy and how you would confirm each.

5-8 years experience
  1. 1

    Design a capacity plan for a fleet of nodes serving a 200M-vector collection with an in-memory configuration. Include the graph, payload indexes, and headroom, and specify the node size and count.

  2. 2

    You must reduce the memory footprint of an in-memory collection by 25 percent without changing the recall target. Walk through the levers (m, quantization, payload indexes, on-disk placement) and the impact of each.

8+ years experience
  1. 1

    Derive the memory overhead of the HNSW graph as a function of m, point count, and ID representation, and explain how the upper-layer factor depends on the level distribution. Where does the model typically undercount?

  2. 2

    You are designing a capacity planning tool for a vector search fleet. Describe the model, the inputs it needs, and how you would validate its predictions against production telemetry.

Follow-up Questions

  • How would you measure the actual per-point memory overhead of a collection in production, and how would you use that to refine a capacity plan?
  • If the graph overhead is a significant fraction of RAM, what options do you have to reduce it without losing recall, and what are the trade-offs?